using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using GameFramework.Interfaces;
using GameStateManagement;
using GameFramework.Graphics;
using GameFramework.Objects;


namespace GameFramework.Controls
{
    public enum ButtonType
    {
        Static,
        PositionTransition,
        ScaleTransition,
    }

    public enum ButtonState
    {
        NORMAL,
        ONSELECTED,
    }

    public class Button : ThreePointObject, ISelected
    {
        

        FrameModule _normalFrame;
        public FrameModule NormalFrame
        {
            get
            {
                return _normalFrame;
            }
            set
            {
                _normalFrame = value;
            }
        }

        FrameModule _selectedFrame;
        public FrameModule SelectedFrame
        {
            get
            {
                return _selectedFrame;
            }
            set
            {
                _selectedFrame = value;
            }
        }       

        private ButtonType _buttonType;
        public ButtonType ButtonType
        {
            get
            {
                return _buttonType;
            }
            set
            {
                _buttonType = value;
            }
        }

        private ButtonState _buttonState = ButtonState.NORMAL;
        public ButtonState ButtonState
        {
            get
            {
                return _buttonState;
            }
            set
            {
                _buttonState = value;
            }
        }

        private Rectangle _bound = Rectangle.Empty;
        public Rectangle Bound
        {
            get
            {
                return _bound;
            }
            set
            {
                _bound = value;
            }
        }

        private double _remainDelayTime;
        /// <summary>
        /// Delay Time when selected for render.
        /// After this delay time, Selected event will be fire.
        /// By default this time is 0.15 seconds
        /// </summary>
        public TimeSpan SelectedDelayTime = TimeSpan.FromMilliseconds(150);

        public bool IsSelected
        {
            get
            {
                return _buttonState == Controls.ButtonState.ONSELECTED;
            }
        }

        public event EventHandler Selected;
        /// <summary>
        /// Constructor for DynamicButton, by defual this constructor set Button Type by Dynamic
        /// </summary>
        /// <param name="game"></param>
        /// <param name="onPosition"></param>
        /// <param name="activePosition"></param>
        /// <param name="offPosition"></param>
        public Button(Game game, Vector2 onPosition, Vector2 activePosition, Vector2 offPosition)
            : base(game, onPosition, activePosition, offPosition)
        {
            _buttonType = Controls.ButtonType.PositionTransition;
            UnknownActiveTransitionTime = true;
            Reset();
        }

        /// <summary>
        /// Constructor for Static Button
        /// </summary>
        /// <param name="game"></param>
        /// <param name="position"></param>
        public Button(Game game, Vector2 position, ButtonType type)
            : base(game, position, position, position)
        {
            _buttonType = type;
            UnknownActiveTransitionTime = true;
            Reset();
        }

        public virtual void HandleInput(GameTime gameTime, InputState input)
        {
            if (input == null)
                return;

            if (_buttonState == Controls.ButtonState.ONSELECTED)
                return;

            foreach (GestureSample gesture in input.Gestures)
            {
                if (gesture.GestureType == GestureType.Tap)
                {
                    if (MathLibraries.MathLibraries.CheckPointInRectangle(_bound, gesture.Position))
                    {
                        Audio.AudioManager.PlaySound("button_click", false);
                        _buttonState = Controls.ButtonState.ONSELECTED;
                    }
                }
            }
        }

        public void SetBound(int width, int height)
        {
            _bound.Width = width;
            _bound.Height = height;
            _bound.X = (int)(Position.X - width / 2);
            _bound.Y = (int)(Position.Y - height / 2);
        }

        /// <summary>
        /// Set the bound of this button by as the same size width the Normal Frame button.
        /// Only use call this method when you set the Normal Sprite before call it.
        /// </summary>
        public virtual void UseNormalFrameBound()
        {
            Rectangle rect = _normalFrame.Bound;
            SetBound(rect.Width, rect.Height);
        }

        public override void Update(GameTime gameTime)
        {            
            if (_buttonState == Controls.ButtonState.ONSELECTED)
            {
                _remainDelayTime -= gameTime.ElapsedGameTime.TotalMilliseconds;
                if (_remainDelayTime <= 0)
                {
                    AfterSelected();

                    Reset();

                    if (Selected != null)
                        Selected(this, new EventArgs());
                   
                }
                else
                {
                    OnSelected();
                }
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            switch (_buttonState)
            {
                case Controls.ButtonState.NORMAL:
                    OnNormalDraw(gameTime);
                    break;
                case Controls.ButtonState.ONSELECTED:
                    OnSelectedDraw(gameTime);
                    break;
            }           
            base.Draw(gameTime);
        }

        public virtual void OnNormalDraw(GameTime gameTime)
        {
            _normalFrame.Draw(Position);
        }

        public virtual void OnSelectedDraw(GameTime gameTime)
        {
            if (_selectedFrame != null)
            {
                _selectedFrame.Draw(Position);
            }
        }

        public virtual void OnSelected()
        {

        }

        public virtual void AfterSelected()
        {

        }

        public override void OnPositionChange()
        {
            _bound.X = (int)(Position.X - _bound.Width / 2);
            _bound.Y = (int)(Position.Y - _bound.Height / 2);
            base.OnPositionChange();
        }

        public virtual void Reset()
        {
            _buttonState = Controls.ButtonState.NORMAL;
            _remainDelayTime = SelectedDelayTime.TotalMilliseconds;
        }
    }
}
